package com.gopay.bis.ipay.expay.operation;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gopay.bis.ipay.ebank.rsa.CryptoUtil;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.ipay.expay.Body;
import com.gopay.common.domain.bank.ipay.expay.IpayExPayBaseMessage;
import com.gopay.common.domain.bank.ipay.expay.Refund;
import com.gopay.remote.bank.ICertHelper;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.DomDriver;

import net.sf.json.JSONObject;

/**
 * @IpayExpayTransportHelper.java
 * @author jiangxiangjiao
 */
public class IpayExpayParseMessage {
	
	private static Logger logger = LoggerFactory.getLogger(IpayExpayParseMessage.class);
	
	public static final String CHARSET = "utf-8";
	public static final String AES_ENCRYPT = "AES/ECB/PKCS5Padding";
	public static final String RSA_ENCRYPT = "RSA/ECB/PKCS1Padding";
	public static final String RSA_SIGN = "SHA1WithRSA";
	
	private ICertHelper ipayExpayCerHelper;
	
	/**
	 * 生成请求参数，提交8个请求参数
	 * @param baseMsg
	 * @param tranCode 交易服务码
	 * @return Map<String, String> 参数名-参数值
	 */
	public Map<String, String> buildReqParam(BaseMessage baseMsg, String tranCode) throws Exception {
		IpayExPayBaseMessage message = (IpayExPayBaseMessage) baseMsg;
		Map<String, String> param = new HashMap<String, String>();
		String signData = ipayExpayCerHelper.sign(baseMsg);
		byte[] keyBytes = generateKeyBytes(16);
		PublicKey yhPubKey = CryptoUtil.getRSAPublicKeyByFileSuffix(baseMsg.getPublicKeyPath(), "pem", "RSA");
		// RSA加密随机密钥
		byte[] rsaKeyBytes = CryptoUtil.RSAEncrypt(keyBytes, yhPubKey, 2048, 11,RSA_ENCRYPT);
		String encrtptKey = new String(Base64.encodeBase64(rsaKeyBytes),CHARSET);
		byte[] data = message.getPlainMessage().getBytes(CHARSET);
		// AES加密报文数据
		byte[] aesDateBytes = CryptoUtil.AESEncrypt(data, keyBytes, "AES",AES_ENCRYPT, null);
		String encryptData = new String(Base64.encodeBase64(aesDateBytes),CHARSET);
		param.put("encryptData", encryptData);
		param.put("encryptKey", encrtptKey);
		param.put("companyId", baseMsg.getMerID());
		param.put("signData", signData);
		param.put("tranCode", tranCode);
		param.put("callBack", baseMsg.getPayNotifyUrl());
		param.put("traceId", message.getTraceId());
		param.put("msgExt", "");
		logger.info("Ipay Expay Submit param : " + param.toString());
		return param;
	}

	public static void main(String[] args) {
		String plainText = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><message><head><version>1.0.0</version><msgType>02</msgType><reqDate>20170316185856</reqDate><respDate>20170316185903</respDate><respType>S</respType><respCode>00</respCode><respMsg>交易成功</respMsg></head><body><reqMsgId>IC17031605339140</reqMsgId><payMsgId>2017031604639068</payMsgId><amount>10</amount><bankCardNo>6225760803340798</bankCardNo><mobilePhone>15901116954</mobilePhone><settleDate>20170316</settleDate></body></message> ";
		XStream xstream = new XStream();
		xstream.autodetectAnnotations(true);
		xstream.processAnnotations(IpayExPayBaseMessage.class);
		IpayExPayBaseMessage result = (IpayExPayBaseMessage) xstream.fromXML(plainText);
		ToStringBuilder.reflectionToString(result);
		
	}
	/**
	 * 解析银行返回的数据并转换成IpayExPayBaseMessage对象
	 * @param response
	 * @param requestMsg
	 * @param bodyCla
	 */
	public IpayExPayBaseMessage parseResponse(BaseMessage baseMsg,String response,Class bodyCla) throws Exception {
		JSONObject jsonObject = JSONObject.fromObject(response);
		String encryptData = jsonObject.getString("encryptData");
		String encryptKey = jsonObject.getString("encryptKey");
		String signData = jsonObject.getString("signData");
		String companyId = jsonObject.getString("companyId");
		String traceId = jsonObject.getString("traceId");
		String msgExt = jsonObject.getString("msgExt");
		String tranCode = jsonObject.getString("tranCode");
		PrivateKey privateKey = CryptoUtil.getRSAPrivateKeyByFileSuffix(baseMsg.getPrivateKeyPath(), "pem", null, "RSA");
		// Base64解密对称密钥
		byte[] base64KeyBytes = Base64.decodeBase64(encryptKey.getBytes(CHARSET));
		// RSA解密对称密钥
		byte[] aesKeyBytes = CryptoUtil.RSADecrypt(base64KeyBytes,privateKey, 2048, 11,RSA_ENCRYPT);
		// Base64解密报文
		byte[] decodeBase64DataBytes = Base64.decodeBase64(encryptData.getBytes(CHARSET));
		// 使用对称密钥解密报文
		byte[] xmlDataBytes = CryptoUtil.AESDecrypt(decodeBase64DataBytes, aesKeyBytes, "AES",AES_ENCRYPT,null);
		// 生成明文报文
		String plainText = new String(xmlDataBytes,CHARSET);
		logger.error("返回明文报文：" + plainText);
		// 将报文数据转化为对象
		
		XStream xstream = new XStream(new DomDriver(CHARSET, new NoNameCoder()));
		xstream.processAnnotations(IpayExPayBaseMessage.class);
		xstream.addDefaultImplementation(bodyCla, Body.class);
		IpayExPayBaseMessage result = (IpayExPayBaseMessage) xstream.fromXML(plainText);
		result.setPublicKeyPath(baseMsg.getPublicKeyPath());
		// 将响应报文数据赋值到响应对象中
		result.setPlainMessage(plainText);
		result.setSignMessage(signData);
		result.setEncryptData(encryptData);
		result.setEncryptKey(encryptKey);
		result.setCompanyId(companyId);
		result.setTraceId(traceId);
		result.setMsgExt(msgExt);
		result.setTranCode(tranCode);
		result.setVerifyFlag((Boolean) ipayExpayCerHelper.verify(result));
		if(result.getHead() != null){
			result.setBankRetCode(result.getHead().getRespCode());
		}
		return result;
	}

	/***
	 * 生成随机对称密钥
	 * @param size 随机密钥长度
	 * @return 随机密钥字节数组
	 */
	public byte[] generateKeyBytes(int size) throws Exception {
		StringBuilder key = new StringBuilder();
		char[] chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
		for (int i = 0; i < size; i++) {
			int index = (int) (Math.random() * (chars.length - 1));
			key.append(chars[index]);
		}
		return key.toString().getBytes(CHARSET);
	}

	public void setIpayExpayCerHelper(ICertHelper ipayExpayCerHelper) {
		this.ipayExpayCerHelper = ipayExpayCerHelper;
	}
	
}
